import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import { Style } from "ol/style";

// t- 添加图层
/**
 *  @description 向地图中添加多个图层
 * @param {*} map 地图对象
 * @param {Array} layers 图层数组
 */
export function addLayers(map, layers) {
  for (let i = 0; i < layers.length; i++) {
    const layer = layers[i];
    map.addLayer(layer);
  }
}

// t- 移除图层
/**
 * @description 移除地图中的多个图层
 * @param {*} map  地图对象
 * @param {Array} layers   图层数组
 */
export function removeLayers(map, layers) {
  layers.forEach(layer => {
    map.removeLayer(layer);
  });
}

/**
 * @description 根据条件函数移除地图中的图层
 * @param {*} map  地图对象
 * @param {Function} condition   条件函数，接收图层属性对象、图层索引和图层数组作为参数，返回布尔值
 * @param {Function} condition.properties  图层属性对象
 * @param {Number} condition.index  图层索引
 * @param {Array} condition.layers  图层数组
 *
 * 注意：
 * 1. 条件函数只会对满足条件的图层进行移除，不会影响其他图层
 * 2. 条件函数的返回值决定是否移除图层，true 表示移除，false 表示不移除
 * 3. 所有满足条件的图层都会被移除
 */
export const removeLayerBy = (map, condition) => {
  const layers = getLayers(map);
  const removedLayers = [];
  layers.forEach((layer, index) => {
    if (condition(layer.getProperties(), index, layers)) {
      removedLayers.push(layer);
    }
  });

  removeLayers(map, removedLayers);
};

// t- 获取/查找图层
/**
 *@abstract  获取地图中的所有图层
 * @param {*} map  地图对象
 * @returns {Array}  地图中的所有图层数组
 */
export function getLayers(map) {
  return map.getLayers().getArray();
}

/**
 *@abstract  根据图层名称获取图层对象
 * @param {*} map  地图对象
 * @param {*} name  图层名称
 * @returns
 *
 * @example
 *  getLayerByName(map, "天地图影像注记").setVisible(false);
 *
 * 注意：
 * 1. 图层名称必须唯一，否则会返回第一个名称匹配的图层对象
 * 2. 图层名称必需要添加在 properties 对象中，否则会返回 undefined
 * 例如：
 * const layer = new VectorLayer({
 *   properties: {
 *     name: "myLayer"
 *   }
 * });
 */
export function getLayerByName(map, name) {
  let targetLayer;
  getLayers(map).forEach(layer => {
    if (layer.get("name") === name) {
      targetLayer = layer;
    }
  });

  return targetLayer;
}

/**
 *  @abstract  根据图层 id 获取图层对象
 * @param {*} map  地图对象
 * @param {*} id  图层 id
 * @returns
 */
export function getLayerById(map, id) {
  let targetLayer;
  getLayers(map).forEach(layer => {
    if (layer.get("id") === id) {
      targetLayer = layer;
    }
  });

  return targetLayer;
}

/**
 *@abstract  根据图层属性查找图层对象
 * @param {*} map  地图对象
 * @param {*} callbackFn  回调函数，接收图层属性对象作为参数，返回布尔值
 * @param {*} callbackFn.properties  图层属性对象
 * @returns
 *
 * @example
 *  findLayer(map, layer => layer.name === "天地图影像注记").setVisible(false);
 */
export function findLayer(map, callbackFn) {
  let targetLayer;
  const layers = getLayers(map);
  layers.forEach((layer, index) => {
    if (callbackFn(layer.getProperties(), index, layers)) {
      targetLayer = layer;
    }
  });

  return targetLayer;
}



// t- 创建图层

/**
 *  @abstract  创建一个矢量图层
 * @param {*} map  地图对象
 * @param {*} layerName  图层名称
 * @param {Array | Function | Style} style    图层样式
 */
export function getVectorLayer({ map, layerName, style, zIndex = 0 }) {
  const getStyle = typeof style === "function" ? style : () => style;

  let vectorLayer = getLayerByName(map, layerName);

  if (!vectorLayer) {
    vectorLayer = new VectorLayer({
      source: new VectorSource(),
      style: style
        ? function (feature) {
            return getStyle(feature);
          }
        : null,
      properties: {
        name: layerName,
      },
      zIndex: zIndex,
    });

    map.addLayer(vectorLayer);
  }

  return vectorLayer;
}
